---
description:
  Learn how to create a GraphQL schema and how to query it directly, without a GraphQL server.
---

import { Callout } from '@theguild/components'

# Getting Started

In this chapter, you will learn about the GraphQL schema:

1. How it performs as an API contract between the consumer and the provider
2. How you can use `graphql` library as a basic GraphQL execution mechanism
3. What is a GraphQL operation and how you can use it?

## Getting Started with GraphQL

To get a better understanding of how GraphQL works, you can start by
[reading this tutorial about GraphQL basics](https://graphql.org/learn/).

If you are already familiar with the basics of GraphQL, here's a quick overview:

1. The GraphQL schema is where your GraphQL types are defined.
2. GraphQL's types are connected using fields, and they form a graph.
3. The `Query`, `Mutation` and `Subscription` types are special since they act as an entry point to
   the graph.
4. The GraphQL schema acts as the data provider, and it offers a set of capabilities the consumer
   can use.
5. To get data from a GraphQL schema, you need to write a GraphQL operation (often referred to as
   `query`) that selects the data and fields you need.

In this section of the tutorial, you'll write a simple GraphQL schema, and you'll consume it
directly, just for the learning process.

Later, you'll replace the direct execution with a GraphQL server (based on HTTP protocol), and
you'll add developer tools that will make it super simple to query and access.

## Creating your First GraphQL Schema

There are many ways to create a GraphQL schema - in this tutorial, you are going to use the
schema-first approach, which is included by default when installing yoga (take a look at the end of
this chapter for different solutions for creating your GraphQL schema).

Start by installing `graphql` library in your project, using the following command:

```sh npm2yarn
npm i graphql@16.10.0 graphql-yoga@5.10.4
```

The command above will get you the following libraries installed in the project:

- `graphql` is the GraphQL engine implementation.
- `graphql-yoga` is the GraphQL Yoga package, for now we will use it to construct out GraphQL schema

A GraphQL schema can be written with GraphQL SDL (*S*chema *D*efinition *L*anguage), which is the
GraphQL language for defining your API/contract. The actual code and business logic of each field is
called a GraphQL _resolver_.

So let's get started by creating your first, very-simple, GraphQL schema.

To get started with a simple GraphQL schema, you need to create a SDL file defining our contract:

Create a `src/schema.ts` file with the following content:

```ts filename="src/schema.ts"
const typeDefinitions = /* GraphQL */ `
  type Query {
    hello: String!
  }
`
```

These are our type definitions that describe what data can be retrieved from the schema.

Up next you define the corresponding resolver functions that are used for resolving the data.

```ts filename="src/schema.ts"
const typeDefinitions = /* GraphQL */ `
  type Query {
    hello: String!
  }
`

const resolvers = {
  Query: {
    hello: () => 'Hello World!'
  }
}
```

As you can see the resolver map follows the same structure as the type definitions.

The typename (`Query`) is an object in which the fields (`hello`) are functions that return the
corresponding data of that field.

Now you still need to glue together the type definitions and the resolver map.

```ts filename="src/schema.ts"
import { createSchema } from 'graphql-yoga'

const typeDefinitions = /* GraphQL */ `
  type Query {
    hello: String!
  }
`

const resolvers = {
  Query: {
    hello: () => 'Hello World!'
  }
}

export const schema = createSchema({
  resolvers: [resolvers],
  typeDefs: [typeDefinitions]
})
```

In the code snippet above, you've created or used the following variables:

- `typeDefinitions` - this is your GraphQL schema definition. You've created a `Query` type that
  exposes a field called `hello`, of type `String`
- `resolvers` - the resolver functions are part of the GraphQL schema, and they are the actual
  implementation (code/logic) of the GraphQL schema
- `schema` - a combination of the GraphQL SDL and the resolvers. `createSchema` function is in
  charge of gluing them together into an executable schema we can later use

Now that you have a GraphQL schema, you can use that to fetch data using a GraphQL `query`
operation!

## Query the GraphQL schema

As explained before, the GraphQL schema is only your contract, and it exposes the set of all types
and capabilities that your API layer can do.

To use your GraphQL schema and consume data from it, you will need to write a GraphQL `query`
operation.

Based on the schema you created before, you can use the following query:

```graphql
query {
  hello
}
```

So you don't have to get into all the complexity of running a GraphQL server - you can use this
query and run it against your GraphQL schema and get an immediate result.

To query our local schema, even without any fancy GraphQL client or even a GraphQL server, you can
use GraphQL's `execute` function to just run the schema with the query.

Update the code in `src/main.ts` to contain the following snippet:

```ts filename="src/main.ts"
import { execute, parse } from 'graphql'
import { schema } from './schema'

async function main() {
  const myQuery = parse(/* GraphQL */ `
    query {
      hello
    }
  `)

  const result = await execute({
    schema,
    document: myQuery
  })

  console.log(result)
}

main()
```

Now, try to run our project again (either with `npm run dev` or `npm run start`), you should see in
the output log the following:

```text
{ data: [Object: null prototype] { hello: 'Hello World' } }
```

You can ignore the `[Object: null prototype]`. It is just means that the object does not inherit any
properties from the global Object prototype and is a security measure that is insignificant for this
tutorial.

### So What Happened Here?

First, the GraphQL `query` operation string was parsed it using the `parse` function of `graphql` -
this will create a `DocumentNode` object that can later be executed by GraphQL.

The `DocumentNode` is an abstract syntax tree (AST), an intermediate format that represents the
operation string in a more processable friendly way for machines.

The JSON representation of the `DocumentNode` of the `query { hello }` operation looks like the
following.

```json
{
  "kind": "Document",
  "definitions": [
    {
      "kind": "OperationDefinition",
      "operation": "query",
      "variableDefinitions": [],
      "selectionSet": {
        "kind": "SelectionSet",
        "selections": [
          {
            "kind": "Field",
            "name": {
              "kind": "Name",
              "value": "hello"
            },
            "arguments": []
          }
        ]
      }
    }
  ]
}
```

Then, the `execute` function of `graphql` was called with the following parameters:

1. `schema` - this is the GraphQL schema object you previously created.
2. `myQuery` - this is the `DocumentNode` object created based on our GraphQL query.

The return value of `execute` is the GraphQL result (or, GraphQL response).

The GraphQL engine takes the query, and based on the fields you selected (called the
_Selection-Set_), it runs the resolvers and returns their return value.

The next chapter will teach you how to use your GraphQL schema to create a GraphQL server!

## A Word on the GraphQL Schema

At the core of every GraphQL API, there is a GraphQL schema. So, let's quickly talk about it.

<Callout>
  Note: In this tutorial, we'll only scratch the surface of this topic. If you want to go a bit more
  in-depth and learn more about the GraphQL schema as well as its role in a GraphQL API, be sure to
  check out [this](https://prisma.io/blog/graphql-server-basics-the-schema-ac5e2950214e) excellent
  article.
</Callout>

GraphQL's schemas are usually written in the GraphQL
[Schema Definition Language](https://prisma.io/blog/graphql-sdl-schema-definition-language-6755bcb9ce51)
(SDL). SDL has a type system that allows you to define data structures (just like other strongly
typed programming languages such as Java, TypeScript, Swift, Go, etc.).

How does that help in defining the API for a GraphQL server, though? Every GraphQL schema has three
special _root types_: `Query`, `Mutation`, and `Subscription`. The root types correspond to the
three operation types offered by GraphQL: queries, mutations, and subscriptions. The fields on these
root types are called _root fields_ and define the available API operations.

As an example, consider the simple GraphQL schema we used above:

```graphql
type Query {
  hello: String!
}
```

This schema only has a single root field, called `hello`. When sending queries, mutations or
subscriptions to a GraphQL API, these always need to start with a root field! In this case, we only
have one root field, so there's only one possible query that's accepted by the API.

Let's now consider a slightly more advanced example:

```graphql
type Query {
  users: [User!]!
  user(id: ID!): User
}

type Mutation {
  createUser(name: String!): User!
}

type User {
  id: ID!
  name: String!
}
```

In this case, we have three root fields: `users` and `user` on `Query` as well as `createUser` on
`Mutation`. An additional definition of the `User` type is required because otherwise, the schema
definition would be incomplete.

What are the API operations that can be derived from this schema definition? Well, we know that each
API operation always needs to start with a root field. However, we haven't learned yet what it looks
like when the _type_ of root field is itself another
[object type](http://graphql.org/learn/schema/#object-types-and-fields). This is the case here,
where the types of the root fields are `[User!]!`, `User` and `User!`. In the `hello` example from
before, the type of the root field was a `String`, which is a
[scalar type](http://graphql.org/learn/schema/#scalar-types).

When the type of root field is an object type, you can further expand the query (or
mutation/subscription) with fields of that object type.

Here are the operations that are accepted by a GraphQL API that implements the above schema:

```graphql
# Query for all users
query {
  users {
    id
    name
  }
}

# Query a single user by their id
query {
  user(id: "user-1") {
    id
    name
  }
}

# Query multiple users and a single user by their id
query {
  users {
    id
    name
  }
  user(id: "user-1") {
    id
    name
  }
}

# Create a new user
mutation {
  createUser(name: "Bob") {
    id
    name
  }
}
```

There are a few things to note:

- In these examples, we always query `id` and `name` of the returned `User` objects. We could
  potentially omit either of them. Note, however, that when querying an object type, it is required
  that you query at least one of its fields in a selection set.
- For the fields in the selection set, it doesn't matter whether the type of the root field is
  _required_ or a _list_. In the example schema above, the three root fields all have different
  [type modifiers](http://graphql.org/learn/schema/#lists-and-non-null) (i.e. different combinations
  of being a list and/or required) for the `User` type:
  - For the `users` field, the return type `[User!]!` means it returns a _list_ (which itself cannot
    be `null`) of `User` elements. The list can also not contain elements that are `null`. So,
    you're always guaranteed to either receive an empty list or a list that only contains non-null
    `User` objects.
  - For the `user(id: ID!)` field, the return type `User` means the returned value could be `null`
    _or_ a `User` object.
  - For the `createUser(name: String!)` field, the return type `User!` means this operation always
    returns a `User` object.

You will learn how to write the corresponding resolver function maps for addition type fields in the
following chapters.

### Additional Resources

As mentioned at the beginning of this chapter, there are many ways to build and create your GraphQL
schema.

Here are a few popular open-source libraries:

- [`graphql`](https://graphql.org/graphql-js/type) - you can use raw `graphql` using object classes
  to create your schema
- [`@graphql-tools/schema`](https://graphql-tools.com/docs/generate-schema) - schema-first library
  for creating executable schemas (it is re-exported from `graphql-yoga` for convenience)
- [`grats`](https://github.com/captbaritone/grats) - library for creating GraphQL schemas from
  TypeScript code annotated with comments.
- [`pothos`](https://github.com/hayes/pothos) - library for creating GraphQL schemas in typescript
  using a strongly typed code first approach and a built-in plugin system
- [`gqtx`](https://github.com/sikanhe/gqtx) - library for creating GraphQL schemas in typescript
  using a strongly typed code first approach
- [`nexus-graphql`](https://nexusjs.org) - Declarative, Code-First GraphQL Schemas for
  JavaScript/TypeScript
- [`typegraphql`](https://github.com/MichalLytek/type-graphql) - GraphQL schema and resolvers with
  TypeScript, using classes and decorators
- [`graphql-modules`](https://graphql-modules.com) - schema first library for creating strict,
  reusable GraphQL schema modules
